package com.mapbased.da;

import java.util.*;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2006</p>
 *
 * <p>Company: mapbased.com</p>
 *
 * @author chy_hs(Baily)
 * @version 1.0
 */
public abstract class Cache
{
    private java.util.Map map=(new java.util.HashMap());
    private Object mapLocker=new Object();
    public static final Object NULL=new Object();
    int liveSeconds=5;
    public Object getValue(Object key,Map p)
    {
        if(key == null)
        {
            return this.getDirectValue(p);
        }

        Object o=this.innerGetValue(
            key,p);
        return o == NULL ? null : o;
    }

    private Object innerGetValue(Object key,Map p)
    {

        CacheValueBag bag=null;
        synchronized(mapLocker)
        {
            bag=(CacheValueBag)map.get(key);
            if(bag == null)
            {
                bag=new CacheValueBag();
                map.put(key,bag);
            }
        }
        //////////////////////////////////////////////////
        Object v=bag.getValue();
        if(v != null)
        {

            if(System.currentTimeMillis() - bag.lastGet < liveSeconds * 1000)
            {
                return v;

            }
            if(bag.getting &&
               System.currentTimeMillis() - bag.lastGet < liveSeconds * 3000)
            {
                return v;
            }
        }

        synchronized(bag) //only one thread get
        {
            v=bag.getValue();
            if(v != null &&
               System.currentTimeMillis() - bag.lastGet < liveSeconds * 2000)
            {
                return v; //if rein,out here
            }
            bag.getting=true;
            v=this.getDirectValue(p);
            if(v == null)
            {
                v=NULL;
            }
            bag.setValue(v);
            bag.getting=false;
            return v;
        }

    }

    protected abstract Object getDirectValue(Map p);

    final public void setLiveSeconds(int liveSeconds)
    {
        this.liveSeconds=liveSeconds;
    }
}
